package com.atguigu.spzx.order.service.Impl;

import cn.hutool.core.util.IdUtil;
import com.atguigu.spyx.model.common.Result;
import com.atguigu.spyx.model.common.ResultCodeEnum;
import com.atguigu.spyx.model.common.com.atguigu.spyx.model.entity.h5.CartItem;
import com.atguigu.spyx.model.common.com.atguigu.spyx.model.entity.h5.OrderItem;
import com.atguigu.spyx.model.common.com.atguigu.spyx.model.entity.h5.UserAddress;
import com.atguigu.spyx.model.common.com.atguigu.spyx.model.entity.h5.UserInfo;
import com.atguigu.spyx.model.common.com.atguigu.spyx.model.entity.order.OrderInfo;
import com.atguigu.spyx.model.common.com.atguigu.spyx.model.entity.product.ProductSku;
import com.atguigu.spyx.model.dto.h5.OrderInfoDto;
import com.atguigu.spyx.model.exception.SpzxException;
import com.atguigu.spyx.model.vo.h5.OrderInfoVo;
import com.atguigu.spzx.cart.api.CartClient;
import com.atguigu.spzx.common.interceptor.SpzxUserInterceptor;
import com.atguigu.spzx.order.mapper.OrderInfoMapper;
import com.atguigu.spzx.order.mapper.OrderItemMapper;
import com.atguigu.spzx.order.service.OrderInfoService;
import com.atguigu.spzx.product.api.ProductClient;
import com.atguigu.spzx.user.api.UserClient;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author LT
 * @create 2023-11-21-19:54
 */
@Service
public class OrderInfoServiceImpl implements OrderInfoService {

    @Resource
    CartClient cartClient;
    @Resource
    StringRedisTemplate stringRedisTemplate;
    @Resource
    OrderInfoMapper orderInfoMapper;
    @Resource
    OrderItemMapper orderItemMapper;
    @Resource
    UserClient userClient;
    @Resource
    ProductClient productClient;
    @Transactional(rollbackFor = Exception.class)

    @Override
    public OrderInfoVo trade() {
        Result<List<CartItem>> result = cartClient.checkedCartList();
        if (result.getCode()!=200){
            throw new SpzxException(ResultCodeEnum.ERROR , null);
        }

        List<CartItem> cartItems = result.getData();
        if (CollectionUtils.isEmpty(cartItems)){
            System.out.println("未选中需要购买的商品");
            throw new SpzxException(ResultCodeEnum.ERROR , null);
        }
        BigDecimal totalAmount = cartItems.stream()
                .map(cartItem -> cartItem.getCartPrice()
                        .multiply(new BigDecimal(cartItem.getSkuNum())))
                .reduce((a,b) -> a.add(b))
                .get();
        Long orderId = IdUtil.createSnowflake(1,1).nextId();
        System.out.println(orderId);
        List<OrderItem> orderItems =
        cartItems.stream().map(cartItem -> {
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderId(orderId);
            orderItem.setSkuId(cartItem.getSkuId());
            orderItem.setSkuName(cartItem.getSkuName());
            orderItem.setThumbImg(cartItem.getImgUrl());
            orderItem.setSkuPrice(cartItem.getCartPrice());
            orderItem.setSkuNum(cartItem.getSkuNum());
            return orderItem;
        }).collect(Collectors.toList());

        stringRedisTemplate.opsForValue().set("order:token:"+orderId,"1",60, TimeUnit.MINUTES);
        OrderInfoVo orderInfoVo = new OrderInfoVo();
        orderInfoVo.setOrderItemList(orderItems);
        orderInfoVo.setTotalAmount(totalAmount);
        return orderInfoVo;
    }

    @Override
    public Long submitOrder(OrderInfoDto orderInfoDto) {
        UserInfo userInfo = SpzxUserInterceptor.THREAD_LOCAL.get();

        List<OrderItem> orderItemList = orderInfoDto.getOrderItemList();
        System.out.println(orderItemList);
        Long token = orderItemList.get(0).getOrderId();
        String type = stringRedisTemplate.opsForValue().get("order:token:"+token);
        if(StringUtils.isEmpty(type)){
            throw new SpzxException(ResultCodeEnum.ORDER_SUBMIT_ERROR,null);
        }
        stringRedisTemplate.delete("order:token:"+token);
        orderItemList.forEach(orderItem -> {
            Result<ProductSku> result = productClient.findById(orderItem.getSkuId());
            if (result.getCode()!=200){
                throw new SpzxException(ResultCodeEnum.ERROR, null);
            }
            ProductSku sku = result.getData();
            if (sku.getStockNum()<orderItem.getSkuNum()){
                throw new SpzxException(ResultCodeEnum.SKU_STOCK_ERROR, null);
            }
            if (sku.getSalePrice().compareTo(orderItem.getSkuPrice())!=0){
                throw new SpzxException(ResultCodeEnum.SKU_PRICE_ERROR, null);
            }
        });
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setUserId(userInfo.getId());
        orderInfo.setNickName(userInfo.getNickName());
        String orderNo = IdUtil.createSnowflake(1,1).nextIdStr();
        orderInfo.setOrderNo(orderNo);
        BigDecimal totalAmount = orderItemList.stream().map(orderItem ->
                orderItem.getSkuPrice().multiply(new BigDecimal(orderItem.getSkuNum())))
                .reduce((a,b) -> a.add(b)).get();
        orderInfo.setTotalAmount(totalAmount);
        orderInfo.setOriginalTotalAmount(totalAmount);
        orderInfo.setFeightFee(orderInfoDto.getFeightFee());
        orderInfo.setRemark(orderInfoDto.getRemark());
        Long userAddressId = orderInfoDto.getUserAddressId();
        Result<UserAddress> result = userClient.findUserAddressById(userAddressId);
        if (result.getCode()!=200){
            throw new SpzxException(ResultCodeEnum.ERROR , null);
        }
        UserAddress userAddress = result.getData();
        orderInfo.setReceiverName(userAddress.getName());
        orderInfo.setReceiverPhone(userAddress.getPhone());
        orderInfo.setReceiverTagName(userAddress.getTagName());
        orderInfo.setReceiverProvince(userAddress.getProvinceCode());
        orderInfo.setReceiverCity(userAddress.getCityCode());
        orderInfo.setReceiverDistrict(userAddress.getDistrictCode());
        orderInfo.setReceiverAddress(userAddress.getFullAddress());
        orderInfoMapper.save(orderInfo);


        Long orderId = orderInfo.getId();
        orderItemList.forEach(orderItem ->
                orderItem.setOrderId(orderId));
        orderItemMapper.batchSave(orderItemList);
        if ("1".equals(type)){
            cartClient.deleteCheckedCart();
        }
        return orderId;

    }

    @Override
    public OrderInfo findOrderById(Long orderId) {
        return orderInfoMapper.findOrderById(orderId);
    }

    @Override
    public PageInfo<OrderInfo> orderPage(Integer pageNum, Integer pageSize, Integer orderStatus) {
        PageHelper.startPage(pageNum,pageSize);
        Long userId = SpzxUserInterceptor.THREAD_LOCAL.get().getId();
        List<OrderInfo> orderInfos = orderInfoMapper.orderPage(userId,orderStatus);
        PageInfo pageInfo = new PageInfo<>(orderInfos);
        orderInfos.forEach(orderInfo -> {
            List<OrderItem> orderItems = orderItemMapper.findByOrderId(orderInfo.getId());
            orderInfo.setOrderItemList(orderItems);
        });
        return pageInfo;
    }

    @Override
    public OrderInfoVo buy(Long skuId) {
        Result<ProductSku> result = productClient.findById(skuId);
        if (result.getCode()!=200){
            throw new SpzxException(ResultCodeEnum.ERROR,null);
        }
        ProductSku sku = result.getData();
        Long orderId = IdUtil.createSnowflake(1,1).nextId();
        OrderItem orderItem = new OrderItem();
        orderItem.setOrderId(orderId);
        orderItem.setSkuId(sku.getId());
        orderItem.setSkuName(sku.getSkuName());
        orderItem.setThumbImg(sku.getThumbImg());
        orderItem.setSkuPrice(sku.getSalePrice());
        orderItem.setSkuNum(1);
        stringRedisTemplate.opsForValue().set("order:token:"+orderId,"2",60,TimeUnit.MINUTES);
        OrderInfoVo orderInfoVo = new OrderInfoVo();
        orderInfoVo.setOrderItemList(Arrays.asList(orderItem));
        orderInfoVo.setTotalAmount(sku.getSalePrice());
        return orderInfoVo;
    }

    @Override
    public OrderInfo findOrderByNo(Long orderNo) {
        OrderInfo orderInfo = orderInfoMapper.findOrderByNo(orderNo);
        List<OrderItem> orderItems = orderItemMapper.findByOrderId(orderInfo.getId());
        orderInfo.setOrderItemList(orderItems);
        return orderInfo;
    }

    @Override
    public void updatePayStatus(Long orderNo, Long payType, Long payStatus) {
        orderInfoMapper.updatePayStatus(orderNo,payType,payStatus);
    }
}
